﻿using AutoMapper;
using DataModel.Models;
using IBusinessService;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NurseServiceApi.DTO;
using System.Globalization;
using System.Linq.Expressions;

namespace NurseServiceApi.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class NurseController : ControllerBase
    {
        private readonly ILogger<NurseController> _logger;
        private readonly IAllStatisticsDataService _allService;
        private readonly IBaseConfigService _baseConfigService;
        private readonly IDeptDataService _deptService;
        private readonly IMapper _mapper;

        public NurseController(
            ILogger<NurseController> logger,
            IAllStatisticsDataService allService,
            IBaseConfigService baseConfigService,
            IDeptDataService deptService,
            IMapper mapper)
        {
            _logger = logger;
            _allService = allService;
            _baseConfigService = baseConfigService;
            _deptService = deptService;
            _mapper = mapper;
        }

        [HttpGet(Name = "GetAllStatisticsDataJsonAsync")]
        public async Task<IEnumerable<AllStatisticsDataDTO>> GetAllStatisticsDataJsonAsync(
            string IDataType,
            string? dbKey = "dbFY") // 默认使用db1
        {
            DateTime targetDate = DateTime.Now.Date;
            DateTime nextDay = targetDate.AddDays(1);
            DateTime lastWeekDate = targetDate.AddDays(-7).Date;
            DateTime lastWeekNextDay = lastWeekDate.AddDays(1);

            string HospitalCode = "01";
            if(dbKey == "dbPJ")
            {
                HospitalCode = "02";
            }

            string config = "";
            if(IDataType == "1")
            {
                config = "重点关注业务量";
            }
            else if (IDataType == "2")
            {
                config = "高危患者";
            }
            else if (IDataType == "3")
            {
                config = "重点患者";
            }
            else if (IDataType == "4")
            {
                config = "专科护理操作眼科";
            }
            else if (IDataType == "5")
            {
                config = "专科护理操作耳鼻喉";
            }
            else
            {
                config = "";
            }
            Expression<Func<BaseConfig, bool>> funcWhereConfig = a => a.IIDataType == config && a.Status == 1;

            Expression<Func<AllStatisticsData, bool>> funcWhere = a => a.IDataType == IDataType && a.HospitalCode == HospitalCode;

            // 1. 保留原有_allService.Query查询逻辑，获取统计数据
            var statsData = await _allService.Query(funcWhere, dbKey)
                .Where(d => d.StartDate >= targetDate && d.StartDate < nextDay ||
                            d.StartDate >= lastWeekDate && d.StartDate < lastWeekNextDay)
                .GroupBy(d => d.IIIDataType)
                .Select(g => new AllStatisticsDataDTO
                {
                    IIIDataType = g.Key,
                    Number = g.Where(d => d.StartDate >= targetDate && d.StartDate < nextDay)
                              .Sum(item => item.DataValue)
                              .ToString("0"),
                    LastWeekNum = g.Where(d => d.StartDate >= lastWeekDate && d.StartDate < lastWeekNextDay)
                                  .Sum(item => item.DataValue)
                                  .ToString("0")
                })
                .ToListAsync();

            // 2. 查询BaseConfig表数据（假设通过数据库上下文直接查询）
            var baseConfigs = await _baseConfigService.Query(funcWhereConfig, dbKey).ToListAsync();

            // 3. 内存中左连接BaseConfig和统计数据，模拟SQL的left join
            var result = baseConfigs
                .GroupJoin(
                    statsData,
                    a => a.IIIDataType,       // BaseConfig的关联键
                    b => b.IIIDataType,      // 统计数据的关联键
                    (a, bGroup) => new { a, bGroup }
                )
                .SelectMany(
                    x => x.bGroup.DefaultIfEmpty(),  // 左连接：保留所有BaseConfig记录
                    (x, b) => new AllStatisticsDataDTO
                    {
                        // 保留BaseConfig的字段（需在DTO中添加对应属性）
                        IIIDataType = x.a.IIIDataType,
                        //Sort = x.a.Sort,  // 排序字段

                        // 统计数据（如果没有匹配则为"0"）
                        Number = b?.Number ?? "0",
                        LastWeekNum = b?.LastWeekNum ?? "0"

                        // 可添加BaseConfig的其他字段，如：
                        // ConfigName = x.a.Name,
                        // ...
                    }
                )
                .OrderBy(d => d.Sort)  // 按a.IIDataType排序
                //.ThenBy(d => d.Sort)          // 再按a.sort排序
                .ToList();

            return result.Select((item, index) => new AllStatisticsDataDTO
            {
                Id = (index + 1).ToString(),
                IIIDataType = item.IIIDataType,
                Number = item.Number,
                LastWeekNum = item.LastWeekNum
            }).ToList();
        }

        [HttpGet(Name = "GetAllStatisticsDataByDeptJsonAsync")]
        public async Task<IActionResult> GetAllStatisticsDataByDeptJsonAsync(string IDataType,string? dbKey = "dbFY")
        {
            DateTime targetDate = DateTime.Now.Date;
            DateTime nextDay = targetDate.AddDays(1);
            DateTime lastWeekDate = targetDate.AddDays(-7).Date;
            DateTime lastWeekNextDay = lastWeekDate.AddDays(1);

            string HospitalCode = "01";
            if (dbKey == "dbPJ")
            {
                HospitalCode = "02";
            }


            string config = "";
            if (IDataType == "1")
            {
                config = "重点关注业务量";
            }
            else if (IDataType == "2")
            {
                config = "高危患者";
            }
            else if (IDataType == "3")
            {
                config = "重点患者";
            }
            else if (IDataType == "4")
            {
                config = "专科护理操作眼科";
            }
            else if (IDataType == "5")
            {
                config = "专科护理操作耳鼻喉";
            }
            else
            {
                config = "";
            }
            Expression<Func<BaseConfig, bool>> funcWhereConfig = a => a.IIDataType == config && a.Status == 1;

            Expression<Func<AllStatisticsData, bool>> funcWhere = a => a.IDataType == IDataType && a.HospitalCode == HospitalCode;

            // 1. 保留原有_allService.Query查询逻辑，获取统计数据
            // 1. 保留原有statsData查询逻辑
            var statsData = await _allService.Query(funcWhere, dbKey)
                .Where(d => d.StartDate >= targetDate && d.StartDate < nextDay ||
                           d.StartDate >= lastWeekDate && d.StartDate < lastWeekNextDay)
                .GroupBy(d => new { d.DeptName, d.IIIDataType })
                .Select(g => new AllStatisticsDataDTO
                {
                    DeptName = g.Key.DeptName,
                    IIIDataType = g.Key.IIIDataType,
                    Number = g.Where(d => d.StartDate >= targetDate && d.StartDate < nextDay)
                              .Sum(item => item.DataValue)
                              .ToString("0"),
                    LastWeekNum = g.Where(d => d.StartDate >= lastWeekDate && d.StartDate < lastWeekNextDay)
                                  .Sum(item => item.DataValue)
                                  .ToString("0")
                })
                .ToListAsync();

            // 2. 查询BaseConfig表数据（主表）
            var baseConfigs = await _baseConfigService.Query(funcWhereConfig, dbKey).ToListAsync();

            // 3. 以baseConfigs为主表左连接statsData，关联条件：IIIDataType（可按需调整）
            var result = baseConfigs
                .GroupJoin(
                    statsData,
                    config => config.IIIDataType,  // 主表baseConfigs的关联键（示例：IIIDataType）
                    stat => stat.IIIDataType,      // 从表statsData的关联键（对应IIIDataType）
                    (config, statsGroup) => new { config, statsGroup }  // 关联后的临时对象
                )
                .SelectMany(
                    // 左连接：将分组后的statsData展开，无匹配时用DefaultIfEmpty()保留主表记录
                    x => x.statsGroup.DefaultIfEmpty(),
                    // 映射最终结果（主表字段+从表字段）
                    (x, stat) => new AllStatisticsDataDTO
                    {
                        // 主表baseConfigs的字段（必选，确保主表信息保留）
                        IIIDataType = x.config.IIIDataType,
                        // 从表statsData的部门名称（无匹配时可为空，但后续会过滤）
                        DeptName = stat?.DeptName ?? string.Empty,
                        // 统计数据（无匹配时默认为"0"）
                        Number = stat?.Number ?? "0",
                        LastWeekNum = stat?.LastWeekNum ?? "0",
                        // 主表的排序字段（用于最终排序）
                        Sort = x.config.Sort  // 需在AllStatisticsDataDTO中添加Sort属性
                    }
                )
                // 过滤：确保每个DeptName都有对应的baseConfigs（排除DeptName为空的记录）
                .Where(dto => !string.IsNullOrEmpty(dto.DeptName))
                // 按baseConfigs的sort字段排序
                .OrderBy(dto => dto.Sort)
                .ToList();

            // 处理带行号的完整数据
            var fullData = result
                .GroupBy(d => d.DeptName)
                .SelectMany(group => group
                    .Select((item, index) => new AllStatisticsDataDTO
                    {
                        Id = (index + 1).ToString(),
                        DeptName = item.DeptName,
                        IIIDataType = item.IIIDataType,
                        Number = item.Number,
                        LastWeekNum = item.LastWeekNum
                    })
                )
                .ToList();




            // 1. 先获取去重的部门名称列表（保留原有逻辑）
            var deptOnlyData = statsData
                .Select(d => d.DeptName)
                .Distinct() // 去重
                .Where(dept => !string.IsNullOrEmpty(dept)) // 过滤空值（避免无效关联）
                .Select(dept => new { DeptName = dept })
                .ToList();

            // 2. 查询BaseConfig表中iDataType = '汾阳院区'的数据
            Expression<Func<BaseConfig, bool>> funcWhereConfigDept = a => a.IDataType == (HospitalCode == "01"? "汾阳院区": "浦江院区") && a.Status == 1;
            var baseConfigDept = await _baseConfigService.Query(funcWhereConfigDept, dbKey).ToListAsync();

            // 3. 关联部门列表和BaseConfig，关联条件：DeptName = IIIDataType
            var resultDept = deptOnlyData
                .Join(
                    baseConfigDept,
                    dept => dept.DeptName,       // 部门名称（关联键）
                    config => config.IIIDataType, // BaseConfig的IIIDataType（关联键）
                    (dept, config) => new        // 关联后的结果
                    {
                        DeptName = dept.DeptName,
                        // 可按需添加BaseConfig的其他字段
                        IIIDataType = config.IIIDataType,
                        Sort = config.Sort,
                        // 其他字段...
                    }
                )
                .OrderBy(item => item.Sort) // 按BaseConfig的sort排序
                .Select(dept => new { DeptName = dept.DeptName })
                .ToList();

            // 返回包含两个数据集的匿名对象
            return Ok(new
            {
                FullStatistics = fullData,
                DepartmentsOnly = resultDept
            });
        }


        [HttpGet(Name = "GetDeptDataJsonAsync")]
        public async Task<IEnumerable<DeptDataDTO>> GetDeptDataJsonAsync(string? dbKey = "dbFY")
        {
            DateTime targetDate = DateTime.Now.Date;
            DateTime nextDay = targetDate.AddDays(1);

            string HospitalCode = "01";
            if (dbKey == "dbPJ")
            {
                HospitalCode = "02";
            }

            Expression<Func<DeptData, bool>> funcWhere = a => a.HospitalCode == HospitalCode;


            var allDeptData = await _deptService.Query(funcWhere, dbKey)
                .Where(d => d.StartDate >= targetDate && d.StartDate < nextDay)
                .ToListAsync();

            return allDeptData.Select((item, index) => new DeptDataDTO
            {
                Id = (index + 1).ToString(),
                KS = item.KS,
                ZYRS = item.ZYRS,
                CYRS = item.CYRS,
                SSL = item.SSL,
                KCS = item.KCS,
                CWSYL = item.CWSYL,
                SQDJDS = item.SQDJDS,
                SQDHSJZS = item.SQDHSJZS
            }).ToList();
        }

        [HttpGet(Name = "GetAllStatisticsDataGroupJsonAsync")]
        public async Task<IActionResult> GetAllStatisticsDataGroupJsonAsync(
            string IIIDataType,
            string flag,
            string? dbKey = "dbFY")
        {
            DateTime targetDate = DateTime.Now.Date;
            DateTime nextDay = targetDate.AddDays(1);

            string HospitalCode = "01";
            if (dbKey == "dbPJ")
            {
                HospitalCode = "02";
            }


            Expression<Func<AllStatisticsData, bool>> funcWhere = a => a.IIIDataType == IIIDataType && a.HospitalCode == HospitalCode;

            if (flag == "2")
            {
                nextDay = targetDate.AddMonths(-1).AddDays(1);
                var allDates = new List<DateTime>();
                for (var date = nextDay; date <= targetDate; date = date.AddDays(1))
                {
                    allDates.Add(date);
                }

                var existingData = await _allService.Query(funcWhere, dbKey)
                    .Where(d => d.StartDate.Date >= nextDay && d.StartDate.Date <= targetDate)
                    .GroupBy(d => d.StartDate.Date)
                    .Select(g => new { Date = g.Key, Number = g.Sum(item => item.DataValue) })
                    .ToListAsync();

                var result = allDates
                    .GroupJoin(
                        existingData,
                        date => date,
                        data => data.Date,
                        (date, data) => new { Date = date, Data = data }
                    )
                    .SelectMany(
                        x => x.Data.DefaultIfEmpty(),
                        (x, data) => new {
                            Date = $"{x.Date.Month}.{x.Date.Day}",
                            Number = data?.Number ?? 0
                        }
                    )
                    .OrderBy(item => DateTime.ParseExact(item.Date, "M.d", null))
                    .ToList();

                return Ok(result);
            }
            else if (flag == "3")
            {
                nextDay = targetDate.AddMonths(-13).AddMonths(1);
                var allMonths = new List<DateTime>();
                for (var date = nextDay; date <= targetDate; date = date.AddMonths(1))
                {
                    allMonths.Add(new DateTime(date.Year, date.Month, 1));
                }

                var existingData = await _allService.Query(funcWhere, dbKey)
                    .Where(d => d.StartDate >= nextDay && d.StartDate <= targetDate)
                    .GroupBy(d => new DateTime(d.StartDate.Year, d.StartDate.Month, 1))
                    .Select(g => new { Month = g.Key, Number = g.Sum(item => item.DataValue) })
                    .ToListAsync();

                var result = allMonths
                    .GroupJoin(
                        existingData,
                        month => month,
                        data => data.Month,
                        (month, data) => new { Month = month, Data = data }
                    )
                    .SelectMany(
                        x => x.Data.DefaultIfEmpty(),
                        (x, data) => new {
                            Month = $"{x.Month.Year}.{x.Month.Month}",
                            Number = data?.Number ?? 0
                        }
                    )
                    .OrderBy(item => DateTime.ParseExact(item.Month, "yyyy.M", CultureInfo.InvariantCulture))
                    .ToList();

                return Ok(result);
            }
            else
            {
                nextDay = targetDate.AddDays(1);
                var allStatisticsDataGroup = await _allService.Query(funcWhere, dbKey)
                    .Where(d => d.StartDate >= targetDate && d.StartDate < nextDay)
                    .GroupBy(d => d.DeptName)
                    .Select(g => new { DeptName = g.Key, Number = g.Sum(item => item.DataValue).ToString("0") })
                    .ToListAsync();

                return Ok(allStatisticsDataGroup);
            }
        }


        [HttpGet(Name = "GetStatisticsDataJsonByNameAsync")]
        public async Task<IEnumerable<AllStatisticsDataDTO>> GetStatisticsDataJsonByNameAsync(
    string? dbKey = "dbFY") // 增加日期参数
        {
            // 使用传入的日期或默认日期
            DateTime queryDate = DateTime.Now.Date;
            DateTime nextDay = queryDate.AddDays(1);

            // 根据数据库选择医院代码
            string hospitalCode = dbKey == "dbPJ" ? "02" : "01";

            // 可以从配置文件或数据库获取这些数据类型
            string[] dataTypes = { "空床数", "在院人数", "入院人数", "预入院人数",
                          "手术人次病区排名", "明日住院手术人次", "今日住院三级手术",
                          "今日住院四级手术", "特级护理", "一级护理", "二级护理",
                          "三级护理", "床护比", "护患比", "平均工作量", "护士总数" };

            try
            {
                // 构建查询条件
                Expression<Func<AllStatisticsData, bool>> funcWhere = a =>
                    dataTypes.Contains(a.IIIDataType) && a.HospitalCode == hospitalCode;

                var statisticsData = await _allService.Query(funcWhere, dbKey)
                    .Where(d => d.StartDate >= queryDate && d.StartDate < nextDay)
                    .GroupBy(g => g.IIIDataType) // 显式分组，原代码可能隐含分组
                    .Select(g => new
                    {
                        IIIDataType = g.Key,
                        Number = g.Sum(item => item.DataValue).ToString("0")
                    })
                    .ToListAsync();

                // 确保所有数据类型都有返回，即使值为0
                return dataTypes.Select(type =>
                {
                    var data = statisticsData.FirstOrDefault(d => d.IIIDataType == type);
                    return new AllStatisticsDataDTO
                    {
                        IIIDataType = type switch
                        {
                            "预入院人数" => "日间患者数",
                            "今日住院三级手术" => "三级手术",
                            "今日住院四级手术" => "四级手术",
                            "明日住院手术人次" => "明天住院手术人次",
                            "手术人次病区排名" => "今日住院手术人次",
                            _ => type
                        },
                        Number = data?.Number ?? "0"
                    };
                }).ToList();
            }
            catch (Exception ex)
            {
                // 记录异常日志
                _logger.LogError(ex, "获取统计数据失败");
                throw; // 或返回空列表/默认值，根据业务需求决定
            }
        }



        [HttpGet(Name = "GetStatisticsDataJsonByDeptAsync")]
        public async Task<IActionResult> GetStatisticsDataJsonByDeptAsync(
  string? dbKey = "dbFY") // 增加日期参数
        {
            // 使用传入的日期或默认日期
            DateTime targetDate = DateTime.Now.Date;
            DateTime nextDay = targetDate.AddDays(1);
            DateTime lastWeekDate = targetDate.AddDays(-7).Date;
            DateTime lastWeekNextDay = lastWeekDate.AddDays(1);

            // 根据数据库选择医院代码
            string hospitalCode = dbKey == "dbPJ" ? "02" : "01";

            // 可以从配置文件或数据库获取这些数据类型
            string[] dataTypes = {  "平均工作量", "护士人数","特级护理人次", "病危病重人次" };
            //string[] dataTypes = { "一级护理", "二级护理", "三级护理", "特级护理" };

            try
            {
                // 构建查询条件
                Expression<Func<AllStatisticsData, bool>> funcWhere = a =>
                    dataTypes.Contains(a.IIIDataType) && a.HospitalCode == hospitalCode;

                // 获取完整统计数据
                var allStatisticsData = await _allService.Query(funcWhere, dbKey)
                    .Where(d => d.StartDate >= targetDate && d.StartDate < nextDay ||
                               d.StartDate >= lastWeekDate && d.StartDate < lastWeekNextDay)
                    .GroupBy(d => new { d.DeptName, d.IIIDataType })
                    .Select(g => new AllStatisticsDataDTO
                    {
                        DeptName = g.Key.DeptName,
                        IIIDataType = g.Key.IIIDataType,
                        Number = g.Where(d => d.StartDate >= targetDate && d.StartDate < nextDay).Sum(item=> item.DataValue).ToString(),
                        LastWeekNum = g.Where(d => d.StartDate >= lastWeekDate && d.StartDate < lastWeekNextDay).Sum(item => item.DataValue).ToString()
                    })
                    .ToListAsync();


                return Ok(new
                {
                    FullStatistics = allStatisticsData,
                    DepartmentsOnly = dataTypes
                });
            }
            catch (Exception ex)
            {
                // 记录异常日志
                _logger.LogError(ex, "获取统计数据失败");
                throw; // 或返回空列表/默认值，根据业务需求决定
            }
        }



        [HttpGet(Name = "GetStatisticsDataJsonByDeptGLAsync")]
        public async Task<IActionResult> GetStatisticsDataJsonByDeptGLAsync(
  string? dbKey = "dbFY") // 增加日期参数
        {
            // 使用传入的日期或默认日期
            DateTime targetDate = DateTime.Now.Date;
            DateTime nextDay = targetDate.AddDays(1);
            DateTime lastWeekDate = targetDate.AddDays(-7).Date;
            DateTime lastWeekNextDay = lastWeekDate.AddDays(1);

            // 根据数据库选择医院代码
            string hospitalCode = dbKey == "dbPJ" ? "02" : "01";

            // 可以从配置文件或数据库获取这些数据类型
            //string[] dataTypes = {  "平均工作量", "护士人数","特级护理人次", "病危病重人次" };
            string[] dataTypes = { "一级护理", "二级护理", "三级护理", "特级护理", "当日入院", "手术病人", "病危", "病重", "病人总数" };

            try
            {
                // 构建查询条件
                Expression<Func<AllStatisticsData, bool>> funcWhere = a =>
                    dataTypes.Contains(a.IIIDataType) && a.HospitalCode == hospitalCode;

                // 获取完整统计数据
                var allStatisticsData = await _allService.Query(funcWhere, dbKey)
                    .Where(d => d.StartDate >= targetDate && d.StartDate < nextDay ||
                               d.StartDate >= lastWeekDate && d.StartDate < lastWeekNextDay)
                    .GroupBy(d => new { d.DeptName, d.IIIDataType })
                    .Select(g => new AllStatisticsDataDTO
                    {
                        DeptName = g.Key.DeptName,
                        IIIDataType = g.Key.IIIDataType,
                        Number = g.Where(d => d.StartDate >= targetDate && d.StartDate < nextDay).Sum(item => item.DataValue).ToString(),
                        LastWeekNum = g.Where(d => d.StartDate >= lastWeekDate && d.StartDate < lastWeekNextDay).Sum(item => item.DataValue).ToString()
                    })
                    .ToListAsync();

                // 仅获取去重的部门名称列表
                var deptOnlyData = allStatisticsData
                    .Select(d => d.DeptName)
                    .Distinct() // 去重
                    .Select(dept => new { DeptName = dept }) // 包装成对象
                    .ToList();

                return Ok(new
                {
                    FullStatistics = allStatisticsData,
                    DepartmentsOnly = deptOnlyData
                });
            }
            catch (Exception ex)
            {
                // 记录异常日志
                _logger.LogError(ex, "获取统计数据失败");
                throw; // 或返回空列表/默认值，根据业务需求决定
            }
        }




        [HttpGet(Name = "GetAllStatisticsDataBRGLJsonAsync")]
        public async Task<IActionResult> GetAllStatisticsDataBRGLJsonAsync(
            string IIIDataType,
            string flag)
        {
            DateTime targetDate = DateTime.Now.Date;
            DateTime nextDay = targetDate.AddDays(1);

            Expression<Func<AllStatisticsData, bool>> funcWhere = a => a.IIIDataType == IIIDataType;

            if (flag == "1")//入院病人概览
            {
                nextDay = targetDate.AddMonths(-1).AddDays(1);
                var allDates = new List<DateTime>();
                for (var date = nextDay; date <= targetDate; date = date.AddDays(1))
                {
                    allDates.Add(date);
                }

                var existingData = await _allService.Query(funcWhere)
                    .Where(d => d.StartDate.Date >= nextDay && d.StartDate.Date <= targetDate)
                    .GroupBy(d => d.StartDate.Date)
                    .Select(g => new { Date = g.Key, Number = g.Sum(item => item.DataValue) })
                    .ToListAsync();

                var result = allDates
                    .GroupJoin(
                        existingData,
                        date => date,
                        data => data.Date,
                        (date, data) => new { Date = date, Data = data }
                    )
                    .SelectMany(
                        x => x.Data.DefaultIfEmpty(),
                        (x, data) => new {
                            Date = $"{x.Date.Month}.{x.Date.Day}",
                            Number = data?.Number ?? 0
                        }
                    )
                    .OrderBy(item => DateTime.ParseExact(item.Date, "M.d", null))
                    .ToList();

                return Ok(result);
            }
            else//在院病人概览
            {
                nextDay = targetDate.AddDays(1);
                var allStatisticsDataGroup = await _allService.Query(funcWhere)
                    .Where(d => d.StartDate >= targetDate && d.StartDate < nextDay)
                    .GroupBy(d => d.HospitalCode)
                    .Select(g => new { HospitalCode = g.Key, Number = g.Sum(item => item.DataValue).ToString("0") })
                    .ToListAsync();

                return Ok(allStatisticsDataGroup);
            }
        }



    }
}